package cn.sc.jedis.serialization;

import cn.sc.utils.ParameterValidation;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import java.io.*;
import java.util.*;

/**
 * @ClassName DefaultSerialization
 * @Author 谢卓才
 * @Description jdk序列化
 * @Date 2022/11/13 9:17
 */
public class DefaultSerialization implements Serialization {

    @Override
    public byte[] packObject(Object data) {
        if(data == null) return null;
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        ObjectOutputStream oos = null;
        try {
            oos = new ObjectOutputStream(os);
            oos.writeObject(data);
            return os.toByteArray();
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            if(oos != null){
                try {
                    oos.flush();
                    oos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(os != null){
                try {
                    os.close();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
        }
    }

    @Override
    public <V> Map<byte[],byte[]> packObjectMap(Map<String,V> data) {
        if(CollectionUtils.isEmpty(data)) return null;
        Map<byte[],byte[]> result = new HashMap<>();
        data.forEach((k,v)->{
            result.put(packString(k), packObject(v));
        });
        return result;
    }

    @Override
    public byte[] packString(String data) {
        if(!StringUtils.hasLength(data)) return null;
        return data.getBytes();
    }

    @Override
    public byte[][] packStringMulti(String... data) {
        if(ParameterValidation.isNull(data)) return null;
        byte[][] result = new byte[data.length][];
        for (int i = 0; i < data.length; i++) {
            result[i] = packString(data[i]);
        }
        return result;
    }

    @Override
    public byte[][] packObjectMulti(String... data) {
        if(ParameterValidation.isNull(data)) return null;
        byte[][] result = new byte[data.length][];
        for (int i = 0; i < data.length; i++) {
            result[i] = packObject(data[i]);
        }
        return result;
    }

    @Override
    public <V> V dismantleObject(byte[] data) {
        if(ParameterValidation.isNull(data)) return null;
        ByteArrayInputStream is = new ByteArrayInputStream(data);
        ObjectInputStream ois = null;
        try {
            ois = new ObjectInputStream(is);
            return (V) ois.readObject();
        } catch (IOException | ClassNotFoundException e) {
            throw new RuntimeException(e);
        } finally {
            if(ois != null){
                try {
                    ois.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(is != null){
                try {
                    is.close();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
        }
    }

    @Override
    public String dismantleString(byte[] data) {
        if(ParameterValidation.isNull(data)) return null;
        return new String(data);
    }

    @Override
    public List<String> dismantleStringMulti(List<byte[]> data) {
        if(CollectionUtils.isEmpty(data)) return null;
        List<String> result = new ArrayList<>(data.size());
        for (byte[] datum : data) {
            result.add(dismantleString(datum));
        }
        return result;
    }

    @Override
    public Set<String> dismantleStringMulti(Set<byte[]> data) {
        if(CollectionUtils.isEmpty(data)) return null;
        Set<String> result = new HashSet<>();
        for (byte[] datum : data) {
            result.add(dismantleString(datum));
        }
        return result;
    }

    @Override
    public <V> List<V> dismantleMulti(List<byte[]> data) {
        if(CollectionUtils.isEmpty(data)) return null;
        List result = new ArrayList(data.size());
        for (byte[] datum : data) {
            result.add(dismantleObject(datum));
        }
        return result;
    }

    @Override
    public <V> Map<String, V> dismantleMap(Map<byte[], byte[]> data) {
        if(CollectionUtils.isEmpty(data)) return null;
        Map<String,V> result= new HashMap<>(data.size());
        data.forEach((k,v)->{
            result.put(dismantleString(k),dismantleObject(v));
        });
        return result;
    }

}
